#ifndef SI1143_h
#define SI1143_h

#define IR_ADDRESS 0x5A

// register addresses
#define PART_ID        0x00
#define REV_ID         0x01
#define SEQ_ID         0x02  //Si114x-A11 (MAJOR_SEQ=1, MINOR_SEQ=1)
#define INT_CFG        0x03
#define IRQ_ENABLE     0x04
#define IRQ_MODE1      0x05
#define IRQ_MODE2      0x06
#define HW_KEY         0x07

#define MEAS_RATE      0x08
#define ALS_RATE       0x09
#define PS_RATE        0x0A

#define ALS_LOW_TH0    0x0B
#define ALS_LOW_TH1    0x0C
#define ALS_HI_TH0     0x0D
#define ALS_HI_TH1     0x0E

#define PS_LED21       0x0F
#define PS_LED3        0x10

#define PS1_TH0        0x11
#define PS1_TH1        0x12
#define PS2_TH0        0x13
#define PS2_TH1        0x14
#define PS3_TH0        0x15

#define PS3_TH1        0x16
#define PARAM_WR       0x17
#define COMMAND        0x18

#define RESPONSE       0x20
#define IRQ_STATUS     0x21

#define ALS_VIS_DATA0  0x22
#define ALS_VIS_DATA1  0x23
#define ALS_IR_DATA0   0x24
#define ALS_IR_DATA1   0x25

#define PS1_DATA0      0x26
#define PS1_DATA1      0x27
#define PS2_DATA0      0x28
#define PS2_DATA1      0x29
#define PS3_DATA0      0x2A
#define PS3_DATA1      0x2B


#define AUX_DATA0      0x2C
#define AUX_DATA1      0x2D

#define PARAM_RD       0x2E
#define CHIP_STAT      0x30
#define ANA_IN_KEY     0x3B

// ram addresses

#define I2C_ADDR                  0x00
#define CHLIST                    0x01
#define PSLED12_SELECT            0x02  
#define PSLED3_SELECT             0x03
#define PS_ENCODING               0x05
#define ALS_ENCODING              0x06
#define PS1_ADCMUX                0x07
#define PS2_ADCMUX                0x08
#define PS3_ADCMUX                0x09
#define PS_ADC_COUNTER            0x0A
#define PS_ADC_GAIN               0x0B
#define PS_ADC_MISC               0x0C
#define ALS_IR_ADCMUX             0x0E
#define AUX_ADCMUX                0x0F
#define ALS_VIS_ADC_COUNTER       0x10
#define ALS_VIS_ADC_GAIN          0x11
#define ALS_VIS_ADC_MISC          0x12
#define ALS_HYST                  0x16
#define PS_HYST                   0x17
#define PS_HISTORY                0x18
#define ALS_HISTORY               0x19
#define ADC_OFFSET                0x1A
#define LED_REC                   0x1C
#define ALS_IR_ADC_COUNTER        0x1D
#define ALS_IR_ADC_GAIN           0x1E
#define ALS_IR_ADC_MISC           0x1F

#endif


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/* Si1143 Example */


#define sleep  100
#define led1 57
#define led2 58
#define led3 59
#define led4 60

#include <Wire.h>
#include "SI1143.h";

int bias1,bias2,bias3,PS1,PS2,PS3;
int blinktime,counter,counter1,counter2,Ledposition;
unsigned int Light_Reading;
byte LowB,HighB;
bool selected;

void setup()
{
  Serial.begin(9600);
  pinMode(led1, OUTPUT); 
  pinMode(led2, OUTPUT); 
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT); 
  pinMode(50, OUTPUT);
  
  digitalWrite(50, HIGH);
  delay(25);
  Wire.begin(); // join i2c bus (address optional for master)
  delay(25);
  
  write_reg(HW_KEY, 0x17); // Setting up LED Power to full
  write_reg(PS_LED21,0xFF);
  write_reg(PS_LED3, 0x0F);
  param_set(CHLIST,0b00010111);
  
  char parameter = read_reg(PARAM_RD,1);
// Serial.print("CHLIST = ");
// Serial.println(parameter,BIN);
  delay(1000);
  
  bias();
  
  counter = 0;
  counter1 = 0;
  counter2 = 0;
  selected = 0;
  blinktime = 75;
}

void loop()
{
  write_reg(COMMAND,0b00000101); // Get a reading
  delay(5);
  
  LowB = read_reg(PS1_DATA0,1); // Read the data for the first LED
  HighB = read_reg(PS1_DATA1,1);
  PS1 = ((HighB * 255) + LowB) - bias1;
  
  LowB = read_reg(PS2_DATA0,1);  // Read the data for the second LED
  HighB = read_reg(PS2_DATA1,1);
  PS2 = (HighB * 255) + LowB - bias2;
  
  LowB = read_reg(PS3_DATA0,1);  // Read the data for the third LED
  HighB = read_reg(PS3_DATA1,1);
  PS3 = (HighB * 255) + LowB - bias3;
  
  Light_Reading = read_light();
  if(Light_Reading >= 330) digitalWrite(led4, HIGH);
  else digitalWrite(led4, LOW);

    if(selected != 1) { 
    if (counter > 10 || counter1 > 10 || counter2 > 10){
      selected = 1;   
      touch_select();
  }
   }
  
  if (PS1 > 200 || PS2 > 200 || PS3 > 200){
      if (PS1 > PS2 && PS1 > PS3){
          if (selected == 0){
          digitalWrite(led1, HIGH);
          digitalWrite(led2, LOW);
          digitalWrite(led3, LOW);
          counter++;
          Ledposition = 1;
          counter1 = 0;
          counter2 = 0;
          }
      }else if(PS2 > PS1 && PS2 > PS3){
          if (selected == 0){
          digitalWrite(led1, LOW);
          digitalWrite(led2, HIGH);
          digitalWrite(led3, LOW);
          counter1++;
          Ledposition = 2;
          counter = 0;
          counter2 = 0;
        }
      }else if(PS3 > PS1 && PS3 > PS2){
          if (selected == 0){
          digitalWrite(led1, LOW);
          digitalWrite(led2, LOW);
          digitalWrite(led3, HIGH);
          counter2++;
          Ledposition = 3;
          counter = 0;
          counter1 = 0;
        }
      }
  }else{
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);
    counter = 0;
    counter1 = 0;
    counter2 = 0;
    selected = 0;
  }
  
  //analogWrite(5, map(Light_Reading, 0, 10000, 0, 255));
  
}

unsigned int read_light(){  // Read light sensor
  write_reg(COMMAND,0b00000110);
  delay(sleep);
  byte LowB = read_reg(ALS_VIS_DATA0,1);
  byte HighB = read_reg(ALS_VIS_DATA1,1);
  return (HighB * 255) + LowB;
}

void param_set(byte address, byte val)  // Set Parameter
{
  write_reg(PARAM_WR, val);
  write_reg(COMMAND, 0xA0|address);
}

char read_reg(unsigned char address, int num_data) // Read a Register
{
  unsigned char data;

  Wire.beginTransmission(IR_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();

  Wire.requestFrom(IR_ADDRESS, num_data);
  
  while(Wire.available() < num_data);
  
  return Wire.read();
}

void write_reg(byte address, byte val) {  // Write a resigter
  Wire.beginTransmission(IR_ADDRESS); 
  Wire.write(address);      
  Wire.write(val);       
  Wire.endTransmission();     
}

void bias(void){  // Bias during start up
  
  for (int i=0; i<20; i++){
  write_reg(COMMAND,0b00000101);
  delay(50);
  
  byte LowB = read_reg(PS1_DATA0,1);
  byte HighB = read_reg(PS1_DATA1,1);
  
  bias1 += ((HighB * 255) + LowB) / 20;
  
  LowB = read_reg(PS2_DATA0,1);
  HighB = read_reg(PS2_DATA1,1);
  
  bias2 += ((HighB * 255) + LowB) / 20;
  
  LowB = read_reg(PS3_DATA0,1);
  HighB = read_reg(PS3_DATA1,1);
  
  bias3 += ((HighB * 255) + LowB) / 20;
}  
}

void touch_select(){    // just a blink routine for when something is selected
       switch (Ledposition) {
      case 1:
      
      for (int i = 0; i < 4; i++){
        digitalWrite(led1, LOW);
        delay(blinktime);
        digitalWrite(led1, HIGH);
        delay(blinktime);
      }
      break;
      case 2:
      for (int i = 0; i < 4; i++){
        digitalWrite(led2, LOW);
        delay(blinktime);
        digitalWrite(led2, HIGH);
        delay(blinktime);
      }
      break;
      case 3:
      for (int i = 0; i < 4; i++){
        digitalWrite(led3, LOW);
        delay(blinktime);
        digitalWrite(led3, HIGH);
        delay(blinktime);
      }
      break;
    }  
}